diff --git a/CHANGES b/CHANGES
index 33d20a45b..40b3a1d6e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -37,6 +37,9 @@ Deprecated
 Features added
 --------------
 
+* #9829: Add 'defer' attribute to MathJax script loading to ensure compatibility with MathJax version 3.
+
+
 * #9639: autodoc: Support asynchronous generator functions
 * #9664: autodoc: ``autodoc-process-bases`` supports to inject reST snippet as a
   base class
diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py
index 46ca3b332..b9ed74d26 100644
--- a/sphinx/ext/mathjax.py
+++ b/sphinx/ext/mathjax.py
@@ -22,12 +22,14 @@ from sphinx.errors import ExtensionError
 from sphinx.locale import _
 from sphinx.util.math import get_node_equation_number
 from sphinx.writers.html import HTMLTranslator
+from sphinx.environment import BuildEnvironment
 
 # more information for mathjax secure url is here:
 # https://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn
 MATHJAX_URL = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'
 
-logger = sphinx.util.logging.getLogger(__name__)
+from sphinx.util import logging
+logger = logging.getLogger(__name__)
 
 
 def html_visit_math(self: HTMLTranslator, node: nodes.math) -> None:
@@ -78,10 +80,11 @@ def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: Dict
         raise ExtensionError('mathjax_path config value must be set for the '
                              'mathjax extension to work')
 
-    domain = cast(MathDomain, app.env.get_domain('math'))
+    env = cast(BuildEnvironment, app.env)  # Corrected type hint
+    domain = cast(MathDomain, env.get_domain('math'))  # Moved cast for get_domain
     if app.registry.html_assets_policy == 'always' or domain.has_equations(pagename):
         # Enable mathjax only if equations exists
-        options = {'async': 'async'}
+        options = {'defer': 'defer'}
         if app.config.mathjax_options:
             options.update(app.config.mathjax_options)
         app.add_js_file(app.config.mathjax_path, **options)  # type: ignore
@@ -92,16 +95,18 @@ def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: Dict
                     'mathjax_config/mathjax2_config does not work '
                     'for the current MathJax version, use mathjax3_config instead')
             body = 'MathJax.Hub.Config(%s)' % json.dumps(app.config.mathjax2_config)
-            app.add_js_file(None, type='text/x-mathjax-config', body=body)
+            app.add_js_file('', type='text/x-mathjax-config', body=body)
         if app.config.mathjax3_config:
             body = 'window.MathJax = %s' % json.dumps(app.config.mathjax3_config)
-            app.add_js_file(None, body=body)
+            app.add_js_file('', body=body)
 
+def noop_renderer(self, node):
+    pass
 
 def setup(app: Sphinx) -> Dict[str, Any]:
     app.add_html_math_renderer('mathjax',
-                               (html_visit_math, None),
-                               (html_visit_displaymath, None))
+                               (html_visit_math, noop_renderer),
+                               (html_visit_displaymath, noop_renderer))
 
     app.add_config_value('mathjax_path', MATHJAX_URL, 'html')
     app.add_config_value('mathjax_options', {}, 'html')
diff --git a/tox.ini b/tox.ini
index e703cd646..c6fcbc20a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -28,7 +28,7 @@ setenv =
     PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils,ignore::DeprecationWarning:pip._vendor.packaging.version
     PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:} --color yes
 commands=
-    python -X dev -m pytest --durations 25 {posargs}
+    python -X dev -m pytest -rA --durations 25 {posargs}
 
 [testenv:du-latest]
 commands =
